Completed
Pull Request — master (#1653)
by Aristeides
04:15 queued 02:06
created

rol.extend.initKirkiControl   F

Complexity

Conditions 12
Paths 2560

Size

Total Lines 90

Duplication

Lines 90
Ratio 100 %

Importance

Changes 0
Metric Value
cc 12
nc 2560
nop 0
dl 90
loc 90
rs 2
c 0
b 0
f 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A 4 4 2
A 5 5 1
A 3 3 1
A 3 3 1
A 3 3 1
A 3 3 1
A 3 3 1
A 3 3 1
A 3 3 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like wp.customize.kirkiDynamicControl.extend.initKirkiControl often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* global kirkiL10n, kirki */
2
wp.customize.controlConstructor['kirki-typography'] = wp.customize.kirkiDynamicControl.extend({
3
4 View Code Duplication
	initKirkiControl: function() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
5
6
		'use strict';
7
8
		var control = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
9
		    value   = control.setting._value,
10
		    picker;
11
12
		control.renderFontSelector();
13
		control.renderBackupFontSelector();
14
		control.renderVariantSelector();
15
		control.renderSubsetSelector();
16
17
		// Font-size.
18
		if ( control.params['default']['font-size'] ) {
19
			this.container.on( 'change keyup paste', '.font-size input', function() {
20
				control.saveValue( 'font-size', jQuery( this ).val() );
21
			});
22
		}
23
24
		// Line-height.
25
		if ( control.params['default']['line-height'] ) {
26
			this.container.on( 'change keyup paste', '.line-height input', function() {
27
				control.saveValue( 'line-height', jQuery( this ).val() );
28
			});
29
		}
30
31
		// Margin-top.
32
		if ( control.params['default']['margin-top'] ) {
33
			this.container.on( 'change keyup paste', '.margin-top input', function() {
34
				control.saveValue( 'margin-top', jQuery( this ).val() );
35
			});
36
		}
37
38
		// Margin-bottom.
39
		if ( control.params['default']['margin-bottom'] ) {
40
			this.container.on( 'change keyup paste', '.margin-bottom input', function() {
41
				control.saveValue( 'margin-bottom', jQuery( this ).val() );
42
			});
43
		}
44
45
		// Letter-spacing.
46
		if ( control.params['default']['letter-spacing'] ) {
47
			value['letter-spacing'] = ( jQuery.isNumeric( value['letter-spacing'] ) ) ? value['letter-spacing'] + 'px' : value['letter-spacing'];
48
			this.container.on( 'change keyup paste', '.letter-spacing input', function() {
49
				value['letter-spacing'] = ( jQuery.isNumeric( jQuery( this ).val() ) ) ? jQuery( this ).val() + 'px' : jQuery( this ).val();
50
				control.saveValue( 'letter-spacing', value['letter-spacing'] );
51
			});
52
		}
53
54
		// Word-spacing.
55
		if ( control.params['default']['word-spacing'] ) {
56
			this.container.on( 'change keyup paste', '.word-spacing input', function() {
57
				control.saveValue( 'word-spacing', jQuery( this ).val() );
58
			});
59
		}
60
61
		// Text-align.
62
		if ( control.params['default']['text-align'] ) {
63
			this.container.on( 'change', '.text-align input', function() {
64
				control.saveValue( 'text-align', jQuery( this ).val() );
65
			});
66
		}
67
68
		// Text-transform.
69
		if ( control.params['default']['text-transform'] ) {
70
			jQuery( control.selector + ' .text-transform select' ).selectWoo().on( 'change', function() {
71
				control.saveValue( 'text-transform', jQuery( this ).val() );
72
			});
73
		}
74
75
		// Text-decoration.
76
		if ( control.params['default']['text-decoration'] ) {
77
			jQuery( control.selector + ' .text-decoration select' ).selectWoo().on( 'change', function() {
78
				control.saveValue( 'text-decoration', jQuery( this ).val() );
79
			});
80
		}
81
82
		// Color.
83
		if ( control.params['default'].color ) {
84
			picker = this.container.find( '.kirki-color-control' );
85
			picker.wpColorPicker({
86
				change: function() {
87
					setTimeout( function() {
88
						control.saveValue( 'color', picker.val() );
89
					}, 100 );
90
				}
91
			});
92
		}
93
	},
94
95
	/**
96
	 * Adds the font-families to the font-family dropdown
97
	 * and instantiates selectWoo.
98
	 */
99 View Code Duplication
	renderFontSelector: function() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
100
101
		var control         = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
102
		    selector        = control.selector + ' .font-family select',
103
		    data            = [],
0 ignored issues
show
Unused Code introduced by
The assignment to variable data seems to be never used. Consider removing it.
Loading history...
104
		    standardFonts   = [],
105
		    googleFonts     = [],
106
		    value           = control.setting._value,
107
		    fonts           = control.getFonts(),
108
		    fontSelect;
109
110
		// Format standard fonts as an array.
111
		if ( ! _.isUndefined( fonts.standard ) ) {
112
			_.each( fonts.standard, function( font ) {
113
				standardFonts.push({
114
					id: font.family.replace( /"/g, '&#39' ),
115
					text: font.label
116
				});
117
			});
118
		}
119
120
		// Format google fonts as an array.
121
		if ( ! _.isUndefined( fonts.google ) ) {
122
			_.each( fonts.google, function( font ) {
123
				googleFonts.push({
124
					id: font.family,
125
					text: font.family
126
				});
127
			});
128
		}
129
130
		// Combine forces and build the final data.
131
		data = [
132
			{ text: kirkiL10n.standardFonts, children: standardFonts },
133
			{ text: kirkiL10n.googleFonts, children: googleFonts }
134
		];
135
136
		// Instantiate selectWoo with the data.
137
		fontSelect = jQuery( selector ).selectWoo({
138
			data: data
139
		});
140
141
		// Set the initial value.
142
		if ( value['font-family'] ) {
143
			fontSelect.val( value['font-family'].replace( /'/g, '"' ) ).trigger( 'change' );
144
		}
145
146
		// When the value changes
147
		fontSelect.on( 'change', function() {
148
149
			// Set the value.
150
			control.saveValue( 'font-family', jQuery( this ).val() );
151
152
			// Re-init the font-backup selector.
153
			control.renderBackupFontSelector();
154
155
			// Re-init variants selector.
156
			control.renderVariantSelector();
157
158
			// Re-init subsets selector.
159
			control.renderSubsetSelector();
160
		});
161
	},
162
163
	/**
164
	 * Adds the font-families to the font-family dropdown
165
	 * and instantiates selectWoo.
166
	 */
167
	renderBackupFontSelector: function() {
168
169
		var control       = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
170
		    selector      = control.selector + ' .font-backup select',
171
		    standardFonts = [],
172
		    value         = control.setting._value,
173
		    fontFamily    = value['font-family'],
174
		    fonts         = control.getFonts(),
175
		    fontSelect;
176
177
		if ( _.isUndefined( value['font-backup'] ) || null === value['font-backup'] ) {
178
			value['font-backup'] = '';
179
		}
180
181
		// Hide if we're not on a google-font.
182
		if ( false === kirki.util.webfonts.google.getFont( fontFamily ) ) {
183
			jQuery( control.selector + ' .font-backup' ).hide();
184
			return;
185
		}
186
		jQuery( control.selector + ' .font-backup' ).show();
187
188
		// Format standard fonts as an array.
189
		if ( ! _.isUndefined( fonts.standard ) ) {
190
			_.each( fonts.standard, function( font ) {
191
				standardFonts.push({
192
					id: font.family.replace( /"/g, '&#39' ),
193
					text: font.label
194
				});
195
			});
196
		}
197
198
		// Instantiate selectWoo with the data.
199
		fontSelect = jQuery( selector ).selectWoo({
200
			data: standardFonts
201
		});
202
203
		// Set the initial value.
204
		if ( 'undefined' !== typeof value['font-backup'] ) {
205
			fontSelect.val( value['font-backup'].replace( /'/g, '"' ) ).trigger( 'change' );
206
		}
207
208
		// When the value changes
209
		fontSelect.on( 'change', function() {
210
211
			// Set the value.
212
			control.saveValue( 'font-backup', jQuery( this ).val() );
213
		});
214
	},
215
216
	/**
217
	 * Renders the variants selector using selectWoo
218
	 * Displays font-variants for the currently selected font-family.
219
	 */
220 View Code Duplication
	renderVariantSelector: function() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
221
222
		var control    = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
223
		    value      = control.setting._value,
224
		    fontFamily = value['font-family'],
225
		    variants   = kirki.util.webfonts.google.getVariants( fontFamily ),
226
		    selector   = control.selector + ' .variant select',
227
		    data       = [],
228
		    isValid    = false,
229
		    fontWeight,
230
		    variantSelector,
231
		    fontStyle;
232
233
		if ( false === kirki.util.webfonts.google.getFont( fontFamily ) ) {
234
			jQuery( control.selector + ' .variant' ).hide();
235
			return;
236
		}
237
238
		jQuery( control.selector + ' .variant' ).show();
239
		_.each( variants, function( variant ) {
240
			if ( value.variant === variant ) {
241
				isValid = true;
242
			}
243
			data.push({
244
				id: variant,
245
				text: variant
246
			});
247
		});
248
		if ( ! isValid ) {
249
			value.variant = 'regular';
250
		}
251
252
		if ( jQuery( selector ).hasClass( 'select2-hidden-accessible' ) ) {
253
			jQuery( selector ).selectWoo( 'destroy' );
254
			jQuery( selector ).empty();
255
		}
256
257
		// Instantiate selectWoo with the data.
258
		variantSelector = jQuery( selector ).selectWoo({
259
			data: data
260
		});
261
		variantSelector.val( value.variant ).trigger( 'change' );
262
		variantSelector.on( 'change', function() {
263
			control.saveValue( 'variant', jQuery( this ).val() );
264
265
			fontWeight = ( ! _.isString( value.variant ) ) ? '400' : value.variant.match( /\d/g );
266
			fontWeight = ( ! _.isObject( fontWeight ) ) ? '400' : fontWeight.join( '' );
267
			fontStyle  = ( -1 !== value.variant.indexOf( 'italic' ) ) ? 'italic' : 'normal';
268
269
			control.saveValue( 'font-weight', fontWeight );
270
			control.saveValue( 'font-style', fontStyle );
271
		});
272
	},
273
274
	/**
275
	 * Renders the subsets selector using selectWoo
276
	 * Displays font-subsets for the currently selected font-family.
277
	 */
278
	renderSubsetSelector: function() {
279
280
		var control    = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
281
		    value      = control.setting._value,
282
		    fontFamily = value['font-family'],
283
		    subsets    = kirki.util.webfonts.google.getSubsets( fontFamily ),
284
		    selector   = control.selector + ' .subsets select',
285
		    data       = [],
286
		    validValue = value.subsets,
287
		    subsetSelector;
288
289
		if ( false !== subsets ) {
290
			jQuery( control.selector + ' .subsets' ).show();
291
			_.each( subsets, function( subset ) {
292
293
				if ( _.isObject( validValue ) ) {
294
					if ( -1 === validValue.indexOf( subset ) ) {
295
						validValue = _.reject( validValue, function( subValue ) {
296
							return subValue === subset;
297
						});
298
					}
299
				}
300
301
				data.push({
302
					id: subset,
303
					text: subset
304
				});
305
			});
306
307
		} else {
308
			jQuery( control.selector + ' .subsets' ).hide();
309
		}
310
311
		if ( jQuery( selector ).hasClass( 'select2-hidden-accessible' ) ) {
312
			jQuery( selector ).selectWoo( 'destroy' );
313
			jQuery( selector ).empty();
314
		}
315
316
		// Instantiate selectWoo with the data.
317
		subsetSelector = jQuery( selector ).selectWoo({
318
			data: data
319
		});
320
		subsetSelector.val( validValue ).trigger( 'change' );
321
		subsetSelector.on( 'change', function() {
322
			control.saveValue( 'subsets', jQuery( this ).val() );
323
		});
324
	},
325
326
	/**
327
	 * Get fonts.
328
	 */
329
	getFonts: function() {
330
		var control            = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
331
		    initialGoogleFonts = kirki.util.webfonts.google.getFonts(),
332
		    googleFonts        = {},
333
		    googleFontsSort    = 'alpha',
334
			googleFontsNumber  = 0,
335
		    standardFonts      = {};
336
337
		// Get google fonts.
338
		if ( ! _.isEmpty( control.params.choices.fonts.google ) ) {
339
			if ( 'alpha' === control.params.choices.fonts.google[0] || 'popularity' === control.params.choices.fonts.google[0] || 'trending' === control.params.choices.fonts.google[0] ) {
340
				googleFontsSort = control.params.choices.fonts.google[0];
341
				if ( ! isNaN( control.params.choices.fonts.google[1] ) ) {
342
					googleFontsNumber = parseInt( control.params.choices.fonts.google[1], 10 );
343
				}
344
				googleFonts = kirki.util.webfonts.google.getFonts( googleFontsSort, googleFontsNumber );
345
346
			} else {
347
				_.each( control.params.choices.fonts.google, function( fontName ) {
348
					if ( 'undefined' !== typeof initialGoogleFonts[ fontName ] ) {
349
						googleFonts[ fontName ] = initialGoogleFonts[ fontName ];
350
					}
351
				} );
352
			}
353
		} else {
354
			googleFonts = kirki.util.webfonts.google.getFonts( googleFontsSort, googleFontsNumber );
355
		}
356
357
		// Get standard fonts.
358
		if ( 'undefined' !== typeof control.params.choices && 'undefined' !== typeof control.params.choices && 'undefined' !== typeof control.params.choices.fonts && 'undefined' !== typeof control.params.choices.fonts.standard ) {
359
			_.each( control.params.choices.fonts.standard, function( fontName ) {
360
				if ( 'undefined' !== typeof kirki.util.webfonts.standard.fonts[ fontName ] ) {
361
					standardFonts[ fontName ] = {};
362
					if ( 'undefined' !== kirki.util.webfonts.standard.fonts[ fontName ].stack ) {
363
						standardFonts[ fontName ].family = kirki.util.webfonts.standard.fonts[ fontName ].stack;
364
					} else {
365
						standardFonts[ fontName ].family = googleFonts[ fontName ];
366
					}
367
					if ( 'undefined' !== kirki.util.webfonts.standard.fonts[ fontName ].label ) {
368
						standardFonts[ fontName ].label = kirki.util.webfonts.standard.fonts[ fontName ].label;
369
					} else {
370
						standardFonts[ fontName ].label = googleFonts[ fontName ];
371
					}
372
				} else {
373
					standardFonts[ fontName ] = {
374
						family: fontName,
375
						label: fontName
376
					};
377
				}
378
			} );
379
		} else {
380
			_.each( kirki.util.webfonts.standard.fonts, function( font, id ) {
381
				standardFonts[ id ] = {
382
					family: font.stack,
383
					label: font.label
384
				};
385
			} );
386
		}
387
		return {
388
			google: googleFonts,
389
			standard: standardFonts
390
		};
391
	},
392
393
	/**
394
	 * Saves the value.
395
	 */
396
	saveValue: function( property, value ) {
397
398
		var control = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
399
		    input   = control.container.find( '.typography-hidden-value' ),
400
		    val     = control.setting._value;
401
402
		val[ property ] = value;
403
404
		jQuery( input ).attr( 'value', JSON.stringify( val ) ).trigger( 'change' );
405
		control.setting.set( val );
406
	}
407
});
408